package tech.yuliu.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;
import tech.yuliu.bean.SearchWord;
import tech.yuliu.bean.Word;
import tech.yuliu.dao.WordDao;
import tech.yuliu.service.WordService;
import tech.yuliu.utils.Levenshtein;
import tech.yuliu.utils.ResultJson;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

@Service
@Slf4j
public class WordServiceImpl implements WordService, ApplicationRunner {

    @Autowired
    private WordDao wordDao;

    @Autowired
    Levenshtein levenshtein;

    private List<Word> allWordList;

    @Value("${word.max-search-return}")
    private Integer MAX_SEARCH_RETURN;

    @Value("${word.search-threshold}")
    private Float SEARCH_THRESHOLD;

    @Value("${word.long-word-threshold}")
    private Integer LONG_WORD_THRESHOLD;

    @Override
    public ResultJson searchWord(String wordStr) {
        // 是否为全英文
        boolean isLetter = wordStr.matches("[a-zA-Z]+");
        if (!isLetter) {
            log.error(String.format("参数错误, wordStr: %s", wordStr));
            return ResultJson.parameterError();
        }
        // 转成小写
        wordStr = wordStr.toLowerCase();
        long startTime = System.currentTimeMillis();
        List<SearchWord> resultWordList = new ArrayList<>();
        // 开始搜索
        for (Word word : allWordList) {
            float similarity = levenshtein.getSimilarityRatio(wordStr, word.getContent().toLowerCase());
            SearchWord searchWord = new SearchWord(word.getId(), word.getContent(), word.getCategory(), word.getTran(), word.getPronUk(), word.getPronUs(), word.getSentence(), word.getSentenceCn(), similarity);
            if (similarity > SEARCH_THRESHOLD) {
                resultWordList.add(searchWord);
            }
            // 长单词直接找到了就退出，短单词不退出
            if (wordStr.length() >= LONG_WORD_THRESHOLD && similarity >= 1.0) {
                break;
            }
        }
        // 根据相似度排序
        resultWordList.sort((Comparator.comparing(SearchWord::getSimilarity)).reversed());
        // 去除多余元素
        if (resultWordList.size() > MAX_SEARCH_RETURN) {
            resultWordList = resultWordList.subList(0, MAX_SEARCH_RETURN);
        }
        long endTime = System.currentTimeMillis();
        log.info(String.format("搜索 %s 结束, 耗时%dms,", wordStr, endTime - startTime));
        return ResultJson.ok().data("count", resultWordList.size()).data("word", resultWordList);
    }

    @Override
    public void run(ApplicationArguments args) {
        // 初始化题库到内存
        allWordList = wordDao.extractAllWord();
        log.info(String.format("加载单词到内存成功，总数量：%d", allWordList.size()));
    }
}
